package com.liudy.demo.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.liudy.demo.util.ShellTool;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: demo
 * @description: 导出pdf控制器
 * @author: liudeyong
 * @create: 2019-03-15 16:25
 **/
public class ExportPdfController {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String ROOT_PATH = "";
    /**
     * 聊天记录导出Pdf
     *
     * @param code
     * @return
     * @throws TemplateException
     * @throws IOException
     */
    @GetMapping(value = "/exportPdf")
    public void exportPdf(@RequestParam String code, HttpServletResponse response) throws IOException, TemplateException {

        // 避免重复生成pdf，如果code已经生成了pdf，直接返回。
        String dirPdfPathStr = ROOT_PATH  + "tmppdf";
        File dirPdfPath = new File(dirPdfPathStr);
        if (!dirPdfPath.exists()) {
            dirPdfPath.mkdirs();
        }
        String pdfPath = dirPdfPath.getAbsolutePath() + "/" + code + ".pdf";
        File pdfFile = new File(pdfPath);
        if (pdfFile.exists()) {
            renderPdfFile(response, pdfPath);
            return;
        }

        //查询一条上传记录
        Uploadlog uploadlog = uploadlogService.queryByCode(code);
        if (uploadlog == null) {
            logger.warn("code:{} 没有查询到消息日志，不下载pdf", code);
            return;
        }
        Map<String,Object> data = getContent(uploadlog, code);
        // 获取配置
        Configuration config = new Configuration();
        File tmplateDir = new ClassPathResource("ftl").getFile();
        config.setDirectoryForTemplateLoading(tmplateDir);
        // 第三步：设置模板文件使用的字符集。一般就是utf-8.
        config.setDefaultEncoding("utf-8");
        StringWriter stringWriter = new StringWriter();
        BufferedWriter writer = new BufferedWriter(stringWriter);
        Template tp = config.getTemplate("temp3.ftl");
        tp.setEncoding("utf-8");

        // 渲染html页面
        tp.process(data, writer);
        String htmlStr = stringWriter.toString();
        String dirHtmlPathStr = ROOT_PATH + "tmphtml";
        File dirHtmlPath = new File(dirHtmlPathStr);
        if (!dirHtmlPath.exists()) {
            dirHtmlPath.mkdirs();
        }
        File htmlFile = new File(FileUtil.getRootPath() + "tmphtml/" + code + ".html");
        FileUtils.writeStringToFile(htmlFile, htmlStr, "utf-8");
        // 调用linux的shell命令，将html写到pdf中。，然后将pdf流响应給用户。
        String htmlPath = htmlFile.getAbsolutePath();
        logger.info("根据code：{}使用freemarker渲染生成的html文件地址：{}", code, htmlPath);

        // wkhtmltopdf /data/project/tmphtml/code.html /data/project/tmppdf/code.pdf
        StringBuilder shellCmd = new StringBuilder("wkhtmltopdf")
                .append(" ")
                .append(htmlPath)
                .append(" ")
                .append(pdfPath);
        logger.info("执行的shell命令是：{}", shellCmd.toString());
        try {
            ShellTool.execCmd(shellCmd.toString(), null, null);
        } catch (Exception e) {
            logger.error("Exception:{}", e);
            return;
        }
        renderPdfFile(response, pdfPath);
    }

    private void renderPdfFile(HttpServletResponse response, String pdfPath) throws IOException {
        File file = new File(pdfPath);
        if (file.exists()) {
            long size = file.length();
            // 为了解决中文名称乱码问题 这里是设置文件下载后的名称
            String fileName = file.getName();
            response.reset();
            response.setHeader("Accept-Ranges", "bytes");
            // 设置文件下载是以附件的形式下载
            response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
            response.addHeader("Content-Length", String.valueOf(size));

            ServletOutputStream sos = response.getOutputStream();
            FileInputStream in = new FileInputStream(file);
            BufferedOutputStream outputStream = new BufferedOutputStream(sos);
            byte[] b = new byte[1024];
            int i = 0;
            while ((i = in.read(b)) > 0) {
                outputStream.write(b, 0, i);
            }
            outputStream.flush();
            sos.close();
            outputStream.close();
            in.close();
        }
    }


    // 拼接数据，后续可更改
    private Map<String, Object> getContent(Uploadlog uploadlog, String code) {
        MessageSuccList succList = messageSuccSerivce.queryByCode(code);
        // 查询到聊天记录为空，直接返回
        if (CollectionUtils.isEmpty(succList.getList())) {
            return Maps.newHashMap();
        }

        HashMap<String, Object> variables = Maps.newHashMapWithExpectedSize(4);
        variables.put("code", uploadlog.getCode());
        variables.put("custWxname", uploadlog.getCustWxname());
        variables.put("saleWxname", uploadlog.getSaleWxname());

        //		../../static/headimg/1551750973899.jpg 		改成 /data/project/static/headimg/1551750973899.jpg
        String custIcon = uploadlog.getCustIcon();
        if (StringUtils.isEmpty(custIcon) || custIcon.startsWith("../")) {
            custIcon.replace("../../", "/data/project/");
        }
        String saleIcon = uploadlog.getSaleIcon();
        if (StringUtils.isEmpty(saleIcon) || saleIcon.startsWith("../")) {
            saleIcon.replace("../../", "/data/project/");
        }

        variables.put("custIcon", custIcon);
        variables.put("saleIcon", saleIcon);

        JSONArray list = new JSONArray();
        JSONObject item;
        for (MessageSucc message : succList.getList()) {
            item = new JSONObject();
            item.put("isSend", message.getIsSend());
            item.put("createTime", message.getCreateTime());
            item.put("type", message.getType());
            item.put("content", message.getContent());

            if (ObjectUtils.compare(message.getType(), 3) == 0) {
                // 图片信息
                logger.info("------------code:{} 的图片消息为：{}", code, JSONObject.toJSONString(message));
                String imgFileName = message.getContent();
                // 图片消息
                String imageRootPath = FileUtil.getRootPath() + Constants.IMAGEPATH + code;
                FileUtil.creatFolder(imageRootPath);
                File imageFile = new File(imageRootPath + File.separator + imgFileName);
                if (!imageFile.exists()) {
                    //去OSS下载至本地
                    FileUtil.getOssObject(message.getImgOss(), imageRootPath + File.separator + imgFileName);
                }
                item.put("imgSrc", imageFile.getAbsolutePath());
            }
            list.add(item);
        }
        variables.put("list", list);
        return variables;
    }
}
